package com.me.study.jdk8.functionInterface;

import com.me.study.jdk8.methodReferences.MethodReference;
import org.junit.Before;
import org.junit.Test;

import java.nio.charset.Charset;
import java.util.function.Predicate;

/**
 * JDK 内置的函数式接口--断定型：Predicate <p>
 *     特点：boolean类型判断，作为方法/构造参数
 *
 * @author ME
 * @date   2019/12/17
 */
public class TestPredicate {

    private String string = "a啊打实";

    @Before
    public void before() {
        System.out.println("字符串字节长度为: " + string.getBytes(Charset.defaultCharset()).length);
    }

    @Test
    public void testTest() {
        System.out.println("\ntestTest(): 字节长度是否超出10");

        // 假设有个长度校验的需求, 判断字节长度是否超出10
        Predicate<String> predicate = str -> {
            System.out.println(str.getBytes().length);
            return str.getBytes().length > 10;
        };
        System.out.println(predicate.test(string));
    }

    /**
     * 默认方法 and():
     * <p>用于两个条件判断 逻辑与</p>
     */
    @Test
    public void testAnd() {
        System.out.println("\ntestAnd(): 字节长度是否在5-10字节之间");

        // 假设有个长度校验的需求, 判断字节长度是否在5-10字节之间
        System.out.println(predicateAndPredicate().test(string));
    }


     /**
      * Predicate<String> pre1 = s -> s.isEmpty();<p>
      * Predicate<String> pre2 = String::isEmpty;<p></p>
      *
      * TODO 为什么 predicate.and() 可以引用 String::isEmpty ??? <p>
      *  这是方法引用中的: 引用 第一个参数实例的实例方法    {@link MethodReference#test4()}
      *  @see MethodReference#test4()
      */
    private Predicate<String> predicateAndPredicate() {
        Predicate<String> predicate = s -> {
            return s.getBytes(Charset.defaultCharset()).length >= 5;
        };
        return predicate.and(s -> s.getBytes(Charset.defaultCharset()).length <= 10);
    }

    /**
     * 默认方法 or():
     * <p>用于两个条件判断 逻辑或</p>
     */
    @Test
    public void testOr() {
        System.out.println("\ntestOr(): 字节长度是否 <5, 或者 >10");

        // 假设有个长度校验的需求, 判断字节长度是否 <5, 或者 >10
        Predicate<String> predicate = s -> {
            return s.getBytes(Charset.defaultCharset()).length < 5;
        };
        System.out.println(predicate.or(s -> s.getBytes(Charset.defaultCharset()).length > 10).test(string));
    }

    /**
     * 默认方法 negate():
     * <p>用于两个条件判断 逻辑非(也就是取反)</p>
     */
    @Test
    public void testNegate() {
        System.out.println("\ntestNegate(): (取反实现)字节长度是否 <5, 或者 >10");

        // 假设有个长度校验的需求, 判断字节长度是否 <5, 或者 >10
        Predicate<String> predicate = s -> {
            return s.getBytes(Charset.defaultCharset()).length < 5;
        };
        System.out.println(predicateAndPredicate().negate().test(string));
    }

}
